﻿using Autofac;
using Autofac.Extras.DynamicProxy;
using AutofacDynamicProxy.Cats;
using AutofacDynamicProxy.Dogs;
using AutofacDynamicProxy.Owners;
using Castle.DynamicProxy;
using System;

namespace AutofacDynamicProxy
{
    /*
     *  Autofac是一个依赖注入框架的库，目的是降低类之间的耦合。
     *  IOC的意思是对象不在通过new来创建，而是将对象的特征（接口IDog）注入到容器（ContainerBuilder）,
     *  然后由容器返回需要的示例(IDog的实现)
     *  Autofac调用拦截器实现AOP。
     *  AOP的含义是面向切面编程，属于一种编程范式。
     *  
     *  动态代理是动态生成一个代理类，可以动态的为这个代理类添加一个接口
     *  
     *  此案例来源：晓晨Master
     *  cnblogs.com/stulzq/p/8547839.html
     *  
     */
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("--------------猫，静态代理------------------");
            #region 猫，静态代理
            ICat icat = new Cat();
            var catProxy = new CatProxy(icat);
            catProxy.Eat();
            #endregion

            Console.WriteLine("--------------狗，动态代理------------------");
            #region 狗，动态代理
            //var builder = new ContainerBuilder();
            ////注册拦截器
            //builder.RegisterType<DogInterceptor>();
            ////注册Dog并为其添加拦截器
            //builder.RegisterType<Dog>().As<IDog>().InterceptedBy(typeof(DogInterceptor)).EnableInterfaceInterceptors();
            //var container = builder.Build();
            //var dog = container.Resolve<IDog>();
            //dog.Eat();
            #endregion

            #region 动态代理
            //我们的DynamicProxy动态生成Cat,
            var builder2 = new ContainerBuilder();

            builder2.RegisterType<DogInterceptor>();//注册拦截器
            builder2.RegisterType<Dog>().As<IDog>();//注册Dog

            //注册CatOwner并为其添加拦截器和接口
            builder2.RegisterType<DogOwner>().InterceptedBy(typeof(DogInterceptor))
                .EnableClassInterceptors(ProxyGenerationOptions.Default, additionalInterfaces: typeof(IDog));
            var container2 = builder2.Build();

            //获取CatOwner的代理类
            var catOwner = container2.Resolve<DogOwner>();
            //因为我们的代理类添加了ICat接口，所以我们可以通过反射获取代理类的Eat方法来执行
            catOwner.GetType().GetMethod("Eat").Invoke(catOwner, null);
            #endregion
            Console.Read();
        }
    }
}
